//#include "stm32f4xx_ll_crs.h"
#include "stm32f4xx_ll_rcc.h"
#include "stm32f4xx_ll_bus.h"
#include "stm32f4xx_ll_system.h"
#include "stm32f4xx_ll_exti.h"
#include "stm32f4xx_ll_cortex.h"
#include "stm32f4xx_ll_utils.h"
#include "stm32f4xx_ll_pwr.h"
#include "stm32f4xx_ll_dma.h"
#include "stm32f4xx_ll_spi.h"
#include "stm32f4xx_ll_usart.h"
#include "stm32f4xx_ll_gpio.h"
#include "stm32_eval_spi_flash.h"

#include <stdio.h>
#include "led.h"
#include "uart.h"

void SystemClock_Config(void)
{
    LL_FLASH_SetLatency(LL_FLASH_LATENCY_5);
    while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_5)
    {
    }
    LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
    LL_RCC_HSE_Enable();

    /* Wait till HSE is ready */
    while(LL_RCC_HSE_IsReady() != 1)
    {

    }
    LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_4, 168, LL_RCC_PLLP_DIV_2);
    LL_RCC_PLL_Enable();

    /* Wait till PLL is ready */
    while(LL_RCC_PLL_IsReady() != 1)
    {

    }
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
    LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_4);
    LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);

    /* Wait till System clock is ready */
    while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
    {

    }
    LL_Init1msTick(168000000);
    LL_SetSystemCoreClock(168000000);
}

/********************************************************************************************
* Description :																			
* Initilize the MCU Clock, the GPIO Pins corresponding to the 		
* device and initilize the FSMC with the chosen configuration 		
* Inputs 	:																				
* 				 None 																		
* outputs 	:																				
* 				"1" 			: Operation succeeded								
* 				"0" 			: Operation failure										
* Note: Mandatory for all types of device 									
*********************************************************************************************/
int Init (void)
{
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
    SystemClock_Config();
    
	sFLASH_Init();
//    uart_init();
//    led_init();

//    printf("%s\n\r", __FUNCTION__);

	return 1;
}

/********************************************************************************************
* Description :																			
* Read data from the device 													    
* Inputs :																					
* 				Address 	: Read location  										
* 				Size 		: Length in bytes 										
* 				buffer 		: Address where to write readed data			
* outputs :																				
* 				"1" 			: Operation succeeded								
* 				"0" 			: Operation failure										
* Info :																						
* Alignment and Data size (32/16/8 bits) should be handled in this function 	
* Note : Not Mandatory for SRAM PSRAM and NOR_FLASH 				
*********************************************************************************************/
int Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
	sFLASH_ReadBuffer(buffer, Address, Size);
//    printf("%s\n\r", __FUNCTION__);
    
	return 1;
}

/********************************************************************************************
* Description :																			
* Write data to the device	 														
* Inputs :																				
* 				Address 	: Write location  										
* 				Size 		: Length in bytes 										
* 				buffer 		: Address where to get the data to write		
* outputs :																				
* 				"1" 			: Operation succeeded								
* 				"0" 			: Operation failure									
* Info :																					
* Alignment and Data size (32/16/8 bits) should be handled in this function 	
* Note : Mandatory for all types except SRAM and PSRAM			
*********************************************************************************************/
int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
//    printf("%s\n\r", __FUNCTION__);
	sFLASH_WriteBuffer(buffer, Address, Size);
    
	return 1;
} 

/********************************************************************************************
* Description :																		
* Full erase of the device 															
* Inputs :																					
* 				None 																		
* outputs :																				
* 				"1" : Operation succeeded											
* 				"0" : Operation failure													
* Info :																					
* Note : Not Mandatory for SRAM PSRAM and NOR_FLASH		
*********************************************************************************************/
int MassErase (void)
{
	sFLASH_EraseBulk();
//    printf("%s\n\r", __FUNCTION__);
    
	return 1;
}

/********************************************************************************************
* Description :																			
* Erase a full sector in the device 												
* Inputs :																					
* 				SectrorAddress	: Start of sector 								
* outputs :																				
* 				"1" : Operation succeeded											
* 				"0" : Operation failure													
* Note : Not Mandatory for SRAM PSRAM and NOR_FLASH		
*********************************************************************************************/
int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{
	EraseStartAddress = EraseStartAddress -  EraseStartAddress%0x01000;//0x10000;litao
	while (EraseEndAddress>=EraseStartAddress)
	{
	 sFLASH_EraseSector(EraseStartAddress);
	 EraseStartAddress += 0x01000;//0x10000;litao
	}
//    printf("%s\n\r", __FUNCTION__);
    
 	return 1;	
}

/********************************************************************************************
* Description :                                                                                                                                
* Initilize the MCU Clock, the GPIO Pins corresponding to the           
* device and initilize the FSMC with the chosen configuration           
* Inputs    :                                                                                                                                 
*      FlashAddr   : Flash address                               
*      RAMBufferAddr : RAM buffer address                           
*      Size         : Size (in WORD)                      
* outputs   :                                                                                                                                 
*     "0"          : Operation succeeded                          
*     address of failure : Operation failed (address of failure)  
* Note: Optional for all types of device                          
********************************************************************************************/
int Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size)
{ 
    uint32_t VerifiedData = 0;
    uint8_t TmpBuffer = 0x00;
    Size*=4;

//    printf("%s\n\r", __FUNCTION__);
    
    while (Size>VerifiedData)
    {
        sFLASH_ReadBuffer(&TmpBuffer, MemoryAddr+VerifiedData, 1);

        if (TmpBuffer != *((uint8_t*)RAMBufferAddr+VerifiedData))
        return MemoryAddr+VerifiedData;

        VerifiedData++;  
    }
        
    return 0;
}

